package com.AdvancedDemos.正则表达式;

import java.util.Scanner;

public class 书写规则_与_练习 {
    public static void main(String[] args) {
        /**
         * Regex书写规则:
         *
         * 字符类(只匹配单个字符):
         * [abc]:只能是a,b,c
         * [^abc]:除了a,b,c之外的任何字符
         * [a-zA-Z]:a到z A到Z 包括(范围)
         * [a-d[m-p]]:a到d 或 m到p
         * [a-z&&[def]]:d,e,f(交集)
         * [a-z&&[^bc]]:a到z,除了b和c(等同于[ad-z])
         * [a-z&&[^m-p]]:a到z,除了m到p(等同于[a-lq-z])
         * [\u4e00-\u9fa5]:任意中文字符
         *
         * 预定义字符(只匹配单个字符):
         * . 匹配除换行符以外的任意字符
         * \d 一个数字:[0-9]
         * \D 非数字[^0-9]
         * \s 一个空白字符
         * \S 非空白字符[^\s]
         * \w [a-zA-Z_0-9]一个单词字符(小写大写下划线数字)
         * \W [^\w]一个非单词字符
         * \b 匹配单词的开始或结束
         *  ^ 匹配字符串的开始
         *  $ 匹配字符串的结束
         *
         * 数量词:
         * x? x,一次或0次
         * x* x,0次或多次
         * x+ x,一次或多次
         * x{n} x,正好n次
         * x{n, } x,至少n次
         * x{n,m} x,至少n但不超过m次
         */


        //1.字符类(只能匹配单个字符)
        System.out.println("a".matches("[abc]"));//[abc]只能匹配a,b,c
        System.out.println("e".matches("[abcd]"));
        //true
        //false
        System.out.println("d".matches("[^abc]"));//[^abc]不能是abc
        System.out.println("a".matches("[^abc]"));
        //true
        //false
        System.out.println("b".matches("[a-zA-Z]"));//[a-zA-Z]只能是a-z A-Z的字符
        System.out.println("2".matches("[a-zA-Z]"));
        //true
        //false
        System.out.println("k".matches("[a-z&&[^bc]]"));//a-z且不是bc
        System.out.println("b".matches("[a-z&&[^bc]]"));
        //true
        //false
        System.out.println("ab".matches("[a-zA-Z0-9]"));//[]只能匹配单个字
        //false
        System.out.println("王天培".matches("[\\u4e00-\\u9fa5]"));//[\u4e00-\u9fa5]匹配单个中文字符
        System.out.println("培".matches("[\\u4e00-\\u9fa5]"));
        System.out.println("W".matches("[\\u4e00-\\u9fa5]"));
        //false
        //true
        //false

        //2.预定义字符(只能匹配单个字符)
        System.out.println("徐".matches("."));//.可以匹配任意字符
        System.out.println("徐徐".matches("."));
        //true
        //false
        System.out.println("3".matches("\\d"));//\d代表:0-9
        System.out.println("a".matches("\\d"));
        System.out.println("123".matches("\\d"));
        /*\\d表示\d,前面一个\用于转义,如果只写\d则会被字符串认为是转义字符,而实际上并不存在一个叫\d的转义字符,所以会报错*/
        //true
        //false
        //false
        System.out.println(" ".matches("\\s"));//\s代表:一个空白字符
        System.out.println("a".matches("\\s"));
        //true
        //false
        System.out.println("b".matches("\\S"));//\S代表:一个非空白字符
        System.out.println(" ".matches("\\S"));
        //true
        //false
        System.out.println("C".matches("\\w"));//\w代表:[a-zA-Z_0-9]
        System.out.println("_".matches("\\w"));
        System.out.println("3".matches("\\w"));
        System.out.println("王".matches("\\w"));
        //true
        //true
        //true
        //false
        System.out.println("张三".matches("\\W"));//[^\W]表示:不能是a-z A-Z _ 0-9
        System.out.println("刘".matches("\\W"));
        System.out.println("G".matches("\\W"));
        //false
        //true
        //false

        //3.数量词
        System.out.println("a".matches("\\w?"));//?代表0次或1次
        System.out.println("".matches("\\w?"));
        System.out.println("_".matches("\\w?"));
        System.out.println("abc".matches("\\w?"));
        //true
        //true
        //true
        //false
        System.out.println("abc12".matches("\\w*"));//*代表0次或多次
        System.out.println("".matches("\\w*"));
        System.out.println("abc12张".matches("\\w*"));
        //true
        //true
        //false
        System.out.println("ABC12".matches("\\w+"));//+代表1次或多次
        System.out.println("".matches("\\w+"));
        System.out.println("_".matches("\\w+"));
        System.out.println("bcd321李".matches("\\w+"));
        //true
        //false
        //true
        //false
        System.out.println("a3c".matches("\\w{3}"));//{3}代表正好是3次
        System.out.println("abcd".matches("\\w{3}"));
        System.out.println("abcd".matches("\\w{3,}"));//{3,}代表>=3次
        System.out.println("abc123".matches("\\w{3,9}"));//{3,9}代表>=3次&&<=9次
        //true
        //false
        //true
        //true

        //4.其他几个常用的符号 (?i)忽略大小写   或|   分组()
        //需求1:要求要么是3个小写字母,要么是3个数字
        System.out.println("需求1--------");
//        String str = "123";//true
        String str = "abc";//true
//        String str = "a1b";//false
//        String str = "1234";//false
//        String str = "1a2";//false
        System.out.println(str.matches("([a-z]{3})|(\\d{3})"));

        //需求2:必须是"我爱"开头,中间可以是至少一个"编程",最后至少是1个"666"
        System.out.println("需求2--------");
        String str1 = "我爱编程666";
        System.out.println(str1.matches("(我爱){1}(编程)+(666)+"));//true
        str1 = "我爱编程666666";
        System.out.println(str1.matches("(我爱){1}(编程)+(666)+"));//true
        str1 = "我爱编程6666666";
        System.out.println(str1.matches("(我爱){1}(编程)+(666)+"));//false
        str1 = "我爱爱编程666";
        System.out.println(str1.matches("(我爱){1}(编程)+(666)+"));//false
        str1 = "我爱编程编程编程666666666";
        System.out.println(str1.matches("(我爱){1}(编程)+(666)+"));//true


        /**
         * 练习:
         * 使用正则表达式校验用户输入的电话是否合法
         */
        System.out.println("----------------");
//        checkPhone();

        /**
         * 练习:
         * 使用正则表达式校验用户输入的邮箱是否合法
         */
        System.out.println("----------------");
//        checkEmail();

        /**
         * 练习:
         * 使用正则表达式校验用户输入的时间是否合法
         */
        System.out.println("----------------");
        checkTime();

    }


    /**
     * 校验电话号码(手机|座机)格式
     */
    private static void checkPhone() {
        Scanner sc = new Scanner(System.in);
        while (true) {
            System.out.println("请输入电话号码(手机|座机):");
            String phoneNumber = sc.nextLine();

            //13220328744 010-12345678 01012345678
            if (phoneNumber.matches("(1[3-9]\\d{9})|(0\\d{2,7}-?[1-9]\\d{4,19})")) {
                //左边表示以1开头第二位是[3-9],后面还有{9}位全部都是数字\d
                //使用"|"表示或,用于连接两个Regex规则,()用于规则分组
                //右边表示以0开头然后加上{2-7}位数字\d作为区号,再加上一个可有可无的分隔符-,后面是一位数字[1-9]再加上{4-19}位数字\d作为电话号码
                System.out.println("格式正确~");
                break;
            } else {
                System.out.println("您输入的号码格式错误");
                System.out.println("请重输!");
            }
        }
    }


    /**
     * 校验邮箱格式
     */
    private static void checkEmail() {
        Scanner sc = new Scanner(System.in);
        while (true) {
            System.out.println("请输入您的邮箱:");
            String email = sc.nextLine();

            //dlei999@163.com
            //1234567890@qq.com
            //itheima@itcast.com.cn
            if (email.matches("\\w{2,}@\\w{2,20}(\\.\\w{2,10})+")) {//.在Regex中表示任意字符,要用转义字符,\\.,第一个\表示将第二个\转义,然后正则表达式中\.有表示.的转义

                System.out.println("格式正确~");
                break;
            } else {
                System.out.println("您输入的邮件地址格式错误");
                System.out.println("请重输!");
            }
        }
    }


    /**
     * 校验时间格式
     */
    private static void checkTime() {
        Scanner sc = new Scanner(System.in);
        while (true) {
            System.out.println("请输入时间:");
            String email = sc.nextLine();

            //12:36
            //09:10
            //23:59
            //00:00
            if (email.matches("^(([01]\\d)|(2[0-3])):[0-5]\\d$")) {
                System.out.println("格式正确~");
                break;
            } else {
                System.out.println("您输入的邮件地址格式错误");
                System.out.println("请重输!");
            }
        }
    }
}
